#include <iostream>
#include <signal.h>
#include "./include/mysql.h"
#include <sys/epoll.h>
#include <fcntl.h>
#include <unordered_map>
#include <regex>
#include <mutex>
#include "../comm/util.hpp"
#include "../comm/httplib.h"
#include "oj_control.hpp"
#include "oj_view.hpp"
#include "ThreadPool.hpp"

using namespace httplib;
using namespace ns_control;
using namespace ns_threadpool;

static Control *ctrl_ptr = nullptr;
std::mutex map_mutex; 

void Recovery(int signo)
{
    ctrl_ptr->RecoveryMachines();
}

#define MAX_EVENTS 1024
#define BUFFER_SIZE 4096

//  用于处理连接的对象
class Connection
{
public:
    int fd;
    std::string read_buf;
    std::string write_buf;
    bool keep_alive;
    std::mutex write_mutex; // 保护写缓冲区的互斥锁

    //  重载移动赋值，由于锁无法赋值给其他对象
    Connection &operator=(Connection &&other) noexcept
    {
        if (this != &other)
        {
            fd = other.fd;
            read_buf = std::move(other.read_buf);
            write_buf = std::move(other.write_buf);
            keep_alive = other.keep_alive;
        }
        return *this;
    }
};

int main()
{
    Control ctrl;
    ctrl_ptr = &ctrl;

    // 创建监听socket
    int listen_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
    if (listen_fd < 0)
    {
        perror("socket");
        return 1;
    }

    // 设置端口复用
    int opt = 1;
    setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    // 绑定地址
    sockaddr_in addr{};
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8080);
    addr.sin_addr.s_addr = INADDR_ANY;
    if (bind(listen_fd, (sockaddr *)&addr, sizeof(addr)) < 0)
    {
        perror("bind");
        return 1;
    }

    // 开始监听
    if (listen(listen_fd, SOMAXCONN) < 0)
    {
        perror("listen");
        return 1;
    }

    // 创建epoll实例
    int epoll_fd = epoll_create1(0);
    if (epoll_fd < 0)
    {
        perror("epoll_create1");
        return 1;
    }

    // 添加listen socket到epoll
    epoll_event event{};
    event.events = EPOLLIN | EPOLLET;
    event.data.fd = listen_fd;
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &event) < 0)
    {
        perror("epoll_ctl");
        return 1;
    }

    // 连接映射表
    std::unordered_map<int, Connection> connections;
    epoll_event events[MAX_EVENTS];

    // 创建线程池，线程数为处理器核心数的2倍
    ns_threadpool::ThreadPool pool(std::thread::hardware_concurrency() * 2);

    // 主事件循环
    while (true)
    {
        int n = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
        if (n < 0)
        {
            perror("epoll_wait");
            continue;
        }

        for (int i = 0; i < n; ++i)
        {
            int fd = events[i].data.fd;
            if (fd == listen_fd)
            {
                while (true)
                {
                    // 监听新连接到来
                    sockaddr_in client_addr{};
                    socklen_t addr_len = sizeof(client_addr);

                    // accept连接，并将fd设置为非阻塞模式，适配et工作模式
                    int conn_fd = accept4(listen_fd, (sockaddr *)&client_addr, &addr_len, SOCK_NONBLOCK);
                    if (conn_fd < 0)
                    {
                        if (errno == EAGAIN || errno == EWOULDBLOCK)
                            break;
                        perror("accept4 failed");
                        break;
                    }

                    // 添加新连接到epoll
                    event.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
                    event.data.fd = conn_fd;
                    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, conn_fd, &event) < 0)
                    {
                        perror("epoll_ctl failed");
                        close(conn_fd);
                        continue;
                    }

                    connections[conn_fd] = 
                    {
                        conn_fd,
                        "",
                        "",
                        true,
                    };
                }
            }
            else if (events[i].events & EPOLLRDHUP)
            {
                
                pool.enqueue([fd, &connections]()
                {
                    close(fd);
                    std::unique_lock<std::mutex> lock(map_mutex);   // 出作用域自动解锁
                    connections.erase(fd); 
                });
                
            }
            else if (events[i].events & EPOLLIN)
            {
                // 使用线程池处理读取请求
                pool.enqueue([fd, &connections, &ctrl, &epoll_fd]() 
                {
                    // 使用lambda表达式，将任务打包，放入queue队列
                    std::unique_lock<std::mutex> map_lock(map_mutex);  
                    auto &conn = connections[fd];
                    map_lock.unlock();

                    // 读取数据
                    char buf[BUFFER_SIZE];
                    while (true)
                    {
                        ssize_t count = read(fd, buf, sizeof(buf));
                        if (count < 0)
                        {
                            if (errno == EAGAIN || errno == EWOULDBLOCK)
                                break;
                            close(fd);
                            connections.erase(fd);
                            return;
                        }
                        if (count == 0)
                        {
                            close(fd);
                            connections.erase(fd);
                            return;
                        }
                        conn.read_buf.append(buf, count);
                    }

                    //  处理HTTP请求
                    size_t end_pos;
                    //  分离请求报头
                    while ((end_pos = conn.read_buf.find("\r\n\r\n")) != std::string::npos)
                    {
                        std::string request = conn.read_buf.substr(0, end_pos + 4);
                        conn.read_buf.erase(0, end_pos + 4);

                        //  处理请求并生成响应
                        try
                        {
                            Request req;
                            Response resp;
                            
                            //  解析HTTP请求行
                            size_t start = request.find(' ');
                            size_t end = request.find(' ', start + 1);
                            std::string method = request.substr(0, start);
                            std::string path = request.substr(start + 1, end - start - 1);

                            //  使用正则表达式解析路径参数
                            std::smatch match;
                            std::regex question_pattern(R"(/question/(\d+))");
                            std::regex judge_pattern(R"(/judge/(\d+))");

                            //  根据HTTP请求进行路由转发
                            if (path == "/all_questions" && method == "GET")
                            {
                                std::string html;
                                ctrl.AllQuestions(&html);
                                resp.set_content(html, "text/html;charset=utf-8");
                            }
                            else if (std::regex_match(path, match, question_pattern) && method == "GET")
                            {
                                std::string number = match[1];
                                std::string html;
                                ctrl.Question(number, &html);
                                resp.set_content(html, "text/html;charset=utf-8");
                            }
                            else if (std::regex_match(path, match, judge_pattern) && method == "POST")
                            {
                                std::string number = match[1];
                                // 获取POST body
                                size_t body_start = request.find("\r\n\r\n");
                                std::string body = request.substr(body_start + 4);
                                std::string result_json;
                                ctrl.Judge(number, body, &result_json);
                                resp.set_content(result_json, "application/json;charset=utf-8");
                            }
                            else
                            {
                                resp.status = 404;
                                resp.set_content("Not Found", "text/plain");
                            }

                            // 添加响应到写缓冲
                            std::lock_guard<std::mutex> write_lock(conn.write_mutex);
                            conn.write_buf += "HTTP/1.1 200 OK\r\n";
                            conn.write_buf += "Content-Type: " + resp.get_header_value("Content-Type") + "\r\n";
                            conn.write_buf += "Content-Length: " + std::to_string(resp.body.size()) + "\r\n";
                            conn.write_buf += "\r\n";
                            conn.write_buf += resp.body;

                            // 修改epoll事件为写事件
                            epoll_event event{};
                            event.events = EPOLLOUT | EPOLLET | EPOLLRDHUP;
                            event.data.fd = fd;
                            epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &event);
                        }
                        catch (const std::exception &e)
                        {
                            // 处理异常
                            LOG(ERROR) << "处理请求异常: " << e.what() << "\n";
                        }
                    }
                });
            }
            else if (events[i].events & EPOLLOUT)
            {
                pool.enqueue([fd, &connections, &epoll_fd]()
                {
                    std::unique_lock<std::mutex> map_lock(map_mutex);
                    auto &conn = connections[fd];
                    map_lock.unlock();
                    
                    while (!conn.write_buf.empty()) 
                    {
                        ssize_t sent = send(fd, conn.write_buf.data(), conn.write_buf.size(), MSG_NOSIGNAL);
                        if (sent < 0) 
                        {
                            if (errno == EAGAIN || errno == EWOULDBLOCK)
                                break;
                            close(fd);
                            connections.erase(fd);
                            return;
                        }
                        conn.write_buf.erase(0, sent);
                    }

                    if (conn.write_buf.empty()) 
                    {
                        epoll_event event{};
                        event.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
                        event.data.fd = fd;
                        epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &event);

                        if (!conn.keep_alive) {
                            close(fd);
                            connections.erase(fd);
                        }
                    } 
                });
            }
        }
    }
    return 0;
}
